package net.wicp.tams.commons.binlog.bean;

import lombok.AccessLevel;
import lombok.Data;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import net.wicp.tams.commons.apiext.ByteUtil;
import net.wicp.tams.commons.apiext.ByteUtil.AssitRead;
import net.wicp.tams.commons.apiext.StringUtil;
import net.wicp.tams.commons.binlog.IEventRead;
import net.wicp.tams.commons.binlog.constant.EventFlag;
import net.wicp.tams.commons.binlog.constant.EventType;
import net.wicp.tams.commons.binlog.event.ParserNo;

/***
 * 事件执行时需要的Bean
 * 
 * @author andy.zhou
 *
 */
@Data
@Slf4j
public class EventBean {
	private EventHeader head;// 事件头
	private byte[] body;// 事件体
	@Setter(AccessLevel.PRIVATE)
	private IEventRead eventRead;// 事件解析器
	@Setter(AccessLevel.PRIVATE)
	private long beginHead;// 事件头开始位置
	private String fileName;
	

	public IEventRead getEventRead() {
		if (head == null || head.getEventType() == null) {
			return null;
		}
		if (eventRead == null) {
			if (StringUtil.isNull(head.getEventType().getParser())) {
				eventRead = new ParserNo(this);
			} else {
				try {
					eventRead = (IEventRead) Class.forName(head.getEventType().getParser())
							.getConstructor(EventBean.class).newInstance(this);
				} catch (Exception e) {
					log.error(String.format("创建事件解析器出错，事件位置:[%s]", beginHead), e);
					throw new IllegalAccessError(e.getMessage());
				}
			}
		}
		return eventRead;
	}

	/***
	 * 事件头位置
	 * 
	 * @return
	 */
	public long getBeginHead() {
		if (beginHead == 0) {
			beginHead = head.getNextEventPos() - head.getEventSize();
		}
		return beginHead;
	}

	/***
	 * 事件体位置
	 * 
	 * @return
	 */
	public long getBeginBody() {
		return getBeginHead() + 19;
	}

	public EventBean(EventHeader head, byte[] body) {
		this.head = head;
		this.body = body;
	}

	public EventBean(byte[] eventBytes) {
		AssitRead assit = new AssitRead(eventBytes);
		long timestamp = ByteUtil.readLongL(assit.readBytes(4));
		EventType eventType = EventType.get(assit.readByte());
		long serverId = ByteUtil.readLongL(assit.readBytes(4));
		long eventSize = ByteUtil.readLongL(assit.readBytes(4));
		long nextEventPos = ByteUtil.readLongL(assit.readBytes(4));
		EventFlag eventFlag = EventFlag.get(ByteUtil.readIntL(assit.readBytes(2)));
		this.body = assit.readBytes((int) eventSize - 19);
		this.head = EventHeader.builder().timestamp(timestamp).eventType(eventType).serverId(serverId)
				.eventSize(eventSize).nextEventPos(nextEventPos).eventFlag(eventFlag).build();
	}

}
